home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / nr3.c < prev    next >
C/C++ Source or Header  |  1991-07-07  |  29KB  |  1,106 lines

  1. /* net/rom level 3 low level processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5. /* Mods by PA0GRI */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "pktdrvr.h"
  12. #include "iface.h"
  13. #include "netuser.h"
  14. #include "timer.h"
  15. #include "arp.h"
  16. #include "slip.h"
  17. #include "ax25.h"
  18. #include "netrom.h"
  19. #include "nr4.h"
  20. #include "lapb.h"
  21. #include "socket.h"
  22. #include "trace.h"
  23. #include "ip.h"
  24. #include "commands.h"
  25.  
  26. static int accept_bc __ARGS((char *addr,unsigned ifnum));
  27. static struct nr_bind *find_best __ARGS((struct nr_bind *list,unsigned obso));
  28. static struct nr_bind *find_binding __ARGS((struct nr_bind *list,struct nrnbr_tab *neighbor));
  29. static struct nrnbr_tab *find_nrnbr __ARGS((char *, unsigned));
  30. static struct nrnf_tab *find_nrnf __ARGS((char *, unsigned));
  31. static struct nr_bind *find_worst __ARGS((struct nr_bind *list));
  32. static int ismycall __ARGS((char *addr));
  33. #ifdef    notdef
  34. static char *nr_getroute __ARGS((char *));
  35. #endif
  36. static struct raw_nr *Raw_nr;
  37. static int nr_aliasck __ARGS(( char *alias));
  38.  
  39. /* Nodes message broadcast address: "NODES" in shifted ASCII */
  40. char Nr_nodebc[AXALEN] = {
  41.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
  42.     ('0'<<1) | E
  43. };
  44.  
  45. struct nriface Nrifaces[NRNUMIFACE];
  46. unsigned Nr_numiface;
  47. struct nrnbr_tab *Nrnbr_tab[NRNUMCHAINS];
  48. struct nrroute_tab *Nrroute_tab[NRNUMCHAINS];
  49. struct nrnf_tab *Nrnf_tab[NRNUMCHAINS];
  50. unsigned Nr_nfmode = NRNF_NOFILTER;
  51. unsigned short Nr_ttl = 10;
  52. static unsigned Obso_init = 6;
  53. static unsigned Obso_minbc = 5;
  54. static unsigned Nr_maxroutes = 5;
  55. unsigned Nr_autofloor = 10;
  56. int Nr_verbose = 0;
  57. int Nr_derate = 1;            /* Allow automatic derating of routes */
  58. int Nr_promisc = 0;            /* behave promisuously with nr bcasts or not? */
  59. struct iface *Nr_iface;
  60.  
  61. /* send a NET/ROM layer 3 datagram */
  62. void
  63. nr3output(dest, data)
  64. char *dest;
  65. struct mbuf *data;
  66. {
  67.     struct nr3hdr n3hdr;
  68.     struct mbuf *n3b;
  69.  
  70.     memcpy(n3hdr.dest,dest,AXALEN);    /* copy destination field */
  71.     n3hdr.ttl = Nr_ttl;    /* time to live from initializer parm */
  72.  
  73.     if((n3b = htonnr3(&n3hdr)) == NULLBUF){
  74.         free_p(data);
  75.         return;
  76.     }
  77.     append(&n3b, data);
  78.     /* The null interface indicates that the packet needs to have */
  79.     /* an appropriate source address inserted by nr_route */
  80.     nr_route(n3b,NULLAX25);
  81. }
  82.  
  83. /* send IP datagrams across a net/rom network connection */
  84. int
  85. nr_send(bp,iface,gateway,prec,del,tput,rel)
  86. struct mbuf *bp;
  87. struct iface *iface;
  88. int32 gateway;
  89. int prec;
  90. int del;
  91. int tput;
  92. int rel;
  93. {
  94.     struct arp_tab *arp;
  95.  
  96.     dump(iface,IF_TRACE_OUT,CL_NETROM,bp);
  97.     iface->rawsndcnt++;
  98.     iface->lastsent = secclock();
  99.  
  100.     if((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP){
  101.         free_p(bp);    /* drop the packet if no route */
  102.         return -1;
  103.     }
  104.     nr_sendraw(arp->hw_addr, NRPROTO_IP, NRPROTO_IP, bp);
  105.     return 0;
  106. }
  107.  
  108. /* Send arbitrary protocol data on top of a NET/ROM connection */
  109. void
  110. nr_sendraw(dest,family,proto,data)
  111. char *dest;
  112. unsigned family;
  113. unsigned proto;
  114. struct mbuf *data;
  115. {
  116.     struct mbuf *pbp;
  117.     struct nr4hdr n4hdr;
  118.  
  119.     /* Create a "network extension" transport header */
  120.     n4hdr.opcode = NR4OPPID;
  121.     n4hdr.u.pid.family = family;
  122.     n4hdr.u.pid.proto = proto;
  123.  
  124.     if((pbp = htonnr4(&n4hdr)) == NULLBUF){
  125.         free_p(data);
  126.         return;
  127.     }
  128.     append(&pbp,data);        /* Append the data to that */
  129.     nr3output(dest, pbp); /* and pass off to level 3 code */
  130. }
  131.  
  132. /* Arrange for receipt of raw NET/ROM datagrams */
  133. struct raw_nr *
  134. raw_nr(protocol)
  135. char protocol;
  136. {
  137.     register struct raw_nr *rp;
  138.  
  139.     rp = (struct raw_nr *)callocw(1,sizeof(struct raw_nr));
  140.     rp->protocol = protocol;
  141.     rp->next = Raw_nr;
  142.     if(rp->next != NULLRNR)
  143.         rp->next->prev = rp;
  144.     Raw_nr = rp;
  145.     return rp;
  146. }
  147. /* Free a raw NET/ROM descriptor */
  148. void
  149. del_rnr(rpp)
  150. struct raw_nr *rpp;
  151. {
  152.     register struct raw_nr *rp;
  153.  
  154.     /* Do sanity check on arg */
  155.     for(rp = Raw_nr;rp != NULLRNR;rp = rp->next)
  156.         if(rp == rpp)
  157.             break;
  158.     if(rp == NULLRNR)
  159.         return;    /* Doesn't exist */
  160.  
  161.     /* Unlink */
  162.     if(rp->prev != NULLRNR)
  163.         rp->prev->next = rp->next;
  164.     else
  165.         Raw_nr = rp->next;
  166.     if(rp->next != NULLRNR)
  167.         rp->next->prev = rp->prev;
  168.     /* Free resources */
  169.     free_q(&rp->rcvq);
  170.     free((char *)rp);
  171. }
  172.  
  173. /* Figure out if a call is assigned to one of my net/rom
  174.  * interfaces.
  175.  */
  176. static int
  177. ismycall(addr)
  178. char *addr;
  179. {
  180.     register int i;
  181.     int found = 0;
  182.     
  183.     for(i = 0; i < Nr_numiface; i++)
  184.         if(addreq(Nrifaces[i].iface->hwaddr,addr)){
  185.             found = 1;
  186.             break;
  187.         }
  188.  
  189.     return found;
  190. }
  191.  
  192.  
  193. /* Route net/rom network layer packets.
  194.  */
  195. void
  196. nr_route(bp, iaxp)
  197. struct mbuf *bp;            /* network packet */
  198. struct ax25_cb *iaxp;            /* incoming ax25 control block */
  199. {
  200.     struct nr3hdr n3hdr;
  201.     struct nr4hdr n4hdr;
  202.     struct ax25_cb *axp;
  203.     struct mbuf *hbp, *pbp;
  204.     struct raw_nr *rnr;
  205.     register struct nrnbr_tab *np;
  206.     register struct nrroute_tab *rp;
  207.     register struct nr_bind *bindp;
  208.     struct iface *iface;
  209.     unsigned ifnum;
  210.     
  211.     if(ntohnr3(&n3hdr,&bp) == -1){
  212.         free_p(bp);
  213.         return;
  214.     }
  215.     /* If this isn't an internally generated network packet,
  216.      * give the router a chance to record a route back to the
  217.      * sender, in case they aren't in the local node's routing
  218.      * table yet.
  219.      */
  220.     if(iaxp != NULLAX25 /* && ax_lookup(iaxp->remote) != NULLAXR */ ){
  221.             
  222.         /* find the interface number */
  223.         for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  224.             if(iaxp->iface == Nrifaces[ifnum].iface)
  225.                 break;
  226.  
  227.         if(ifnum == Nr_numiface){    /* Not a net/rom interface! */
  228.             free_p(bp);
  229.             return;
  230.         }
  231.         /* Add (possibly) a zero-quality recorded route via */
  232.         /* the neighbor from which this packet was received */
  233.         /* Note that this doesn't work with digipeated neighbors. */
  234.         
  235.         (void) nr_routeadd("##temp",n3hdr.source,ifnum,0,iaxp->remote,0,1);
  236.     }
  237.  
  238.     /* A packet from me, to me, can only be one thing:
  239.      * a horrible routing loop.  This will probably result
  240.      * from a bad manual ARP entry, but we should fix these
  241.      * obscure errors as we find them.
  242.      */
  243.     if(ismycall(n3hdr.dest)){
  244.         /* Toss if from me, or if we can't read the header */
  245.         if(iaxp == NULLAX25 || ntohnr4(&n4hdr,&bp) == -1){
  246.             free_p(bp);
  247.         } else if((n4hdr.opcode & NR4OPCODE) == NR4OPPID){
  248.             for(rnr = Raw_nr;rnr!=NULLRNR;rnr = rnr->next){
  249.                 if(rnr->protocol!=n4hdr.u.pid.family ||
  250.                  rnr->protocol != n4hdr.u.pid.proto)
  251.                     continue;
  252.                 /* Duplicate the data portion, and put the
  253.                  * level 3 header back on
  254.                  */
  255.                 dup_p(&pbp,bp,0,len_p(bp));
  256.                 if(pbp != NULLBUF &&
  257.                  (hbp = htonnr3(&n3hdr)) != NULLBUF){
  258.                     append(&hbp,pbp);
  259.                     enqueue(&rnr->rcvq,hbp);
  260.                 } else {
  261.                     free_p(pbp);
  262.                     free_p(hbp);
  263.                 }
  264.             }
  265.             /* IP does not use a NET/ROM level 3 socket */
  266.             if(n4hdr.u.pid.family == NRPROTO_IP
  267.              && n4hdr.u.pid.proto == NRPROTO_IP)
  268.                 ip_route(iaxp->iface,bp,0);
  269.             else        /* we don't do this proto */
  270.                 free_p(bp);
  271.         } else {
  272.             /* Must be net/rom transport: */
  273.             nr4input(&n4hdr,bp);
  274.         }
  275.         return;
  276.     }
  277.     if((rp = find_nrroute(n3hdr.dest)) == NULLNRRTAB){
  278.         /* no route, drop the packet */
  279.         free_p(bp);
  280.         return;
  281.     }
  282.     if((bindp = find_best(rp->routes,1)) == NULLNRBIND){
  283.         /* This shouldn't happen yet, but might if we add */
  284.         /* dead route detection */
  285.         free_p(bp);
  286.         return;
  287.     }
  288.  
  289.     np = bindp->via;
  290.     iface = Nrifaces[np->iface].iface;
  291.  
  292.     /* Now check to see if iaxp is null.  That is */
  293.     /* a signal that the packet originates here, */
  294.     /* so we need to insert the callsign of the appropriate  */
  295.     /* interface */
  296.     if(iaxp == NULLAX25)
  297.         memcpy(n3hdr.source,iface->hwaddr,AXALEN);
  298.     
  299.     /* Make sure there is a connection to the neighbor */
  300.     if((axp = find_ax25(np->call)) == NULLAX25 ||
  301.         (axp->state != LAPB_CONNECTED && axp->state != LAPB_RECOVERY)){
  302.         /* Open a new connection or reinitialize old one */
  303.         /* hwaddr has been advanced to point to neighbor + digis */
  304.         axp = open_ax25(iface,iface->hwaddr,np->call, AX_ACTIVE, Axwindow, s_arcall, s_atcall, s_ascall,-1);
  305.         if(axp == NULLAX25){
  306.             free_p(bp);
  307.             return;
  308.         }
  309.     }
  310.         
  311.     if(--n3hdr.ttl == 0){    /* the packet's time to live is over! */
  312.         free_p(bp);
  313.         return;
  314.     }
  315.     /* now format network header */
  316.     if((pbp = htonnr3(&n3hdr)) == NULLBUF){
  317.         free_p(bp);
  318.         return;
  319.     }
  320.     append(&pbp,bp);        /* append data to header */
  321.  
  322.     /* put AX.25 PID on front */
  323.     if((bp = pushdown(pbp,1)) == NULLBUF){
  324.         free_p(pbp);
  325.         return;
  326.     }
  327.     bp->data[0] = PID_NETROM;
  328.  
  329.     if((pbp = segmenter(bp,axp->paclen)) == NULLBUF){
  330.         free_p(bp);
  331.         return;
  332.     }
  333.     send_ax25(axp,pbp,-1);    /* pass it off to ax25 code */
  334. }
  335.     
  336.  
  337. /* Perform a nodes broadcast on interface # ifno in the net/rom
  338.  * interface table.
  339.  */
  340. void
  341. nr_bcnodes(ifno)
  342. unsigned ifno;
  343. {
  344.     struct mbuf *hbp, *dbp, *savehdr;
  345.     struct nrroute_tab *rp;
  346.     struct nrnbr_tab *np;
  347.     struct nr_bind * bp;
  348.     struct nr3dest nrdest;
  349.     int i, didsend = 0, numdest = 0;
  350.     register char *cp;
  351.     struct iface *axif = Nrifaces[ifno].iface;
  352.     
  353.     /* prepare the header */
  354.     if((hbp = alloc_mbuf(NR3NODEHL)) == NULLBUF)
  355.         return;
  356.         
  357.     hbp->cnt = NR3NODEHL;    
  358.     
  359.     *hbp->data = NR3NODESIG;
  360.     memcpy(hbp->data+1,Nrifaces[ifno].alias,ALEN);
  361.  
  362.     /* Some people don't want to advertise any routes; they
  363.      * just want to be a terminal node.  In that case we just
  364.      * want to send our call and alias and be done with it.
  365.      */
  366.  
  367.     if(!Nr_verbose){
  368.         (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  369.                         PID_NETROM, hbp);    /* send it */
  370.         return;
  371.     }
  372.  
  373.     /* make a copy of the header in case we need to send more than */
  374.     /* one packet */
  375.     savehdr = copy_p(hbp,NR3NODEHL);
  376.  
  377.     /* now scan through the routing table, finding the best routes */
  378.     /* and their neighbors.  create destination subpackets and append */
  379.     /* them to the header */
  380.     for(i = 0; i < NRNUMCHAINS; i++){
  381.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next){
  382.             /* look for best, non-obsolescent route */
  383.             if((bp = find_best(rp->routes,0)) == NULLNRBIND)
  384.                 continue;    /* no non-obsolescent routes found */
  385.  
  386.             if(bp->quality == 0)    /* this is a loopback route */
  387.                 continue;            /* we never broadcast these */
  388.  
  389.             if (bp->quality < Nr_autofloor)    /* below threshhold route */
  390.                 continue ;        /* so don't broadcast it */
  391.  
  392.             if (nr_aliasck(rp->alias))    /* corrupted alias entry? */
  393.                 continue ;        /* don't rebroadcast it */
  394.                             /* safety measure! */
  395.             np = bp->via;
  396.             /* insert best neighbor */
  397.             memcpy(nrdest.neighbor,np->call,AXALEN);
  398.             /* insert destination from route table */
  399.             memcpy(nrdest.dest,rp->call,AXALEN);
  400.             /* insert alias from route table */
  401.             strcpy(nrdest.alias,rp->alias);
  402.             /* insert quality from binding */
  403.             nrdest.quality = bp->quality;
  404.             /* create a network format destination subpacket */
  405.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  406.                 free_p(hbp);    /* drop the whole idea ... */
  407.                 free_p(savehdr);
  408.                 return;
  409.             }
  410.             /* we now have a partially filled packet */
  411.             didsend = 0;    
  412.             append(&hbp,dbp);    /* append to header and others */
  413.             /* see if we have appended as many destinations
  414.              * as we can fit into a single broadcast.  If we
  415.              * have, go ahead and send them out.
  416.              */
  417.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  418.                 /* indicate that we did broadcast */
  419.                 didsend = 1;
  420.                 /* reset the destination counter */
  421.                 numdest = 0;
  422.                 (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  423.                  PID_NETROM,hbp);    /* send it */
  424.                 /* new header */
  425.                 hbp = copy_p(savehdr,NR3NODEHL);
  426.             }
  427.         }
  428.     }
  429.  
  430.     /* Now, here is something totally weird.  If our interfaces */
  431.     /* have different callsigns than this one, advertise a very */
  432.     /* high quality route to them.  Is this a good idea?  I don't */
  433.     /* know.  However, it allows us to simulate a bunch of net/roms */
  434.     /* hooked together with a diode matrix coupler. */
  435.     for(i = 0; i < Nr_numiface; i++){
  436.         if(i == ifno)
  437.             continue;        /* don't bother with ours */
  438.         cp = Nrifaces[i].iface->hwaddr;
  439.         if(!addreq((char *)axif->hwaddr,cp)){
  440.             /* both destination and neighbor address */
  441.             memcpy(nrdest.dest,cp,AXALEN);
  442.             memcpy(nrdest.neighbor,cp,AXALEN);
  443.             /* alias of the interface */
  444.             strcpy(nrdest.alias,Nrifaces[i].alias);
  445.             /* and the very highest quality */
  446.             nrdest.quality = 255;
  447.             /* create a network format destination subpacket */
  448.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  449.                 free_p(hbp);    /* drop the whole idea ... */
  450.                 free_p(savehdr);
  451.                 return;
  452.             }
  453.             /* we now have a partially filled packet */
  454.             didsend = 0;    
  455.             /* append to header and others */
  456.             append(&hbp,dbp);
  457.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  458.                 /* indicate that we did broadcast */
  459.                 didsend = 1;
  460.                 /* reset the destination counter */
  461.                 numdest = 0;
  462.                 (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  463.                  PID_NETROM,hbp);    /* send it */
  464.                 /* new header */
  465.                 hbp = copy_p(savehdr,NR3NODEHL);
  466.             }
  467.         }
  468.     }
  469.             
  470.     /* If we have a partly filled packet left over, or we never */
  471.     /* sent one at all, we broadcast: */
  472.  
  473.     if(!didsend || numdest > 0) {
  474.         (*axif->output)(axif, Nr_nodebc, axif->hwaddr,PID_NETROM, hbp);
  475.     } else {
  476.         if(numdest == 0)     /* free the header copies */
  477.             free_p(hbp);
  478.     }
  479.  
  480.     free_p(savehdr);
  481. }
  482.  
  483.  
  484.  
  485. /* attach the net/rom interface.  no parms for now. */
  486. int
  487. nr_attach(argc,argv,p)
  488. int argc;
  489. char *argv[];
  490. void *p;
  491. {
  492.     if(Nr_iface != (struct iface *)0){
  493.         tprintf("netrom interface already attached\n");
  494.         return -1;
  495.     }
  496.  
  497.     Nr_iface = (struct iface *)callocw(1,sizeof(struct iface));
  498.     Nr_iface->addr = Ip_addr;
  499.  
  500.     /* The strdup is needed to keep the detach routine happy (it'll
  501.      * free the allocated memory)
  502.      */
  503.     Nr_iface->name = strdup("netrom");
  504.     if(Nr_iface->hwaddr == NULLCHAR){
  505.         Nr_iface->hwaddr = mallocw(AXALEN);
  506.         memcpy(Nr_iface->hwaddr,Mycall,AXALEN);
  507.     }
  508.     Nr_iface->mtu = NR4MAXINFO;
  509.     setencap(Nr_iface,"NETROM");
  510.     Nr_iface->next = Ifaces;
  511.     Ifaces = Nr_iface;
  512.     memcpy(Nr4user,Mycall,AXALEN);
  513.     return 0;
  514. }
  515.  
  516. /* This function checks an ax.25 address and interface number against
  517.  * the filter table and mode, and returns -1 if the address is to be accepted 
  518.  * verbatim, the quality if filtered in or 0 if it is to be filtered out.
  519.  */
  520. static int
  521. accept_bc(addr,ifnum)
  522. char *addr;
  523. unsigned ifnum;
  524. {
  525.     struct nrnf_tab *fp;
  526.  
  527.     if(Nr_nfmode == NRNF_NOFILTER)        /* no filtering in effect */
  528.         return -1;
  529.  
  530.     fp = find_nrnf(addr,ifnum);        /* look it up */
  531.     
  532.     if (fp != NULLNRNFTAB && Nr_nfmode == NRNF_ACCEPT)
  533.         return fp->quality ;
  534.  
  535.     if (fp == NULLNRNFTAB && Nr_nfmode == NRNF_REJECT)
  536.         return -1;
  537.  
  538.     if (Nr_promisc)
  539.         return -1;        /* Come up and see me sometime..... */
  540.     else
  541.         return 0 ;        /* My mummy said not to listen to strangers! */
  542. }
  543.  
  544. /* receive and process node broadcasts. */
  545. void
  546. nr_nodercv(iface,source,bp)
  547. struct iface *iface;
  548. char *source;
  549. struct mbuf *bp;
  550. {
  551.     register int ifnum;
  552.     char bcalias[AXALEN];
  553.     struct nr3dest ds;
  554.     int qual;
  555.     
  556.     /* First, see if this is even a net/rom interface: */
  557.     for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  558.         if(iface == Nrifaces[ifnum].iface)
  559.             break;
  560.             
  561.     if(ifnum == Nr_numiface){    /* not in the interface table */
  562.         free_p(bp);
  563.         return;
  564.     }
  565.  
  566.     if ((qual = accept_bc(source,ifnum)) == 0) {    /* check against filter */
  567.         free_p(bp) ;                /* and get quality */
  568.         return ;
  569.     }
  570.     
  571.     /* See if it has a routing broadcast signature: */
  572.     if(PULLCHAR(&bp) != NR3NODESIG){
  573.         free_p(bp);
  574.         return;
  575.     }
  576.  
  577.     /* now try to get the alias */
  578.     if(pullup(&bp,bcalias,ALEN) < ALEN){
  579.         free_p(bp);
  580.         return;
  581.     }
  582.  
  583.     /* now check that the alias field is not corrupted - saftey measure! */
  584.     if (nr_aliasck(bcalias)) {
  585.         free_p(bp);
  586.         return;
  587.     }
  588.  
  589.     bcalias[ALEN] = '\0';        /* null terminate */
  590.  
  591.     /* enter the neighbor into our routing table */
  592.     if(qual == -1)
  593.         qual = Nrifaces[ifnum].quality;    /* use default quality */
  594.  
  595.     if(nr_routeadd(bcalias, source, ifnum, qual, source, 0, 0) == -1){
  596.         free_p(bp);
  597.         return;
  598.     }
  599.  
  600.     /* we've digested the header; now digest the actual */
  601.     /* routing information */
  602.     while(ntohnrdest(&ds,&bp) != -1){
  603.  
  604.         /* ignore routes to me! */
  605.         if(ismycall(ds.dest))
  606.             continue;
  607.  
  608.         /* ignore routes with corrupted aliases - safety measure */
  609.         if (nr_aliasck (ds.alias))
  610.             continue;
  611.  
  612.         /* ignore loopback paths to ourselves */
  613.         if(ismycall(ds.neighbor))
  614.             continue;
  615.         else
  616.             ds.quality = ((ds.quality * qual + 128) / 256) & 0xff;
  617.  
  618.         /* ignore routes below the minimum quality threshhold */
  619.         if(ds.quality < Nr_autofloor)
  620.             continue;
  621.  
  622.         if(nr_routeadd(ds.alias,ds.dest,ifnum,ds.quality,source,0,0)
  623.             == -1)
  624.             break;
  625.     }            
  626.     free_p(bp);    /* This will free the mbuf if anything fails above */
  627. }
  628.  
  629.  
  630. /* The following are utilities for manipulating the routing table */
  631.  
  632. /* hash function for callsigns.  Look familiar? */
  633. int16
  634. nrhash(s)
  635. char *s;
  636. {
  637.     register char x;
  638.     register int i;
  639.  
  640.     x = 0;
  641.     for(i = ALEN; i !=0; i--)
  642.         x ^= *s++ & 0xfe;
  643.     x ^= *s & SSID;
  644.     return (int16)(uchar(x) % NRNUMCHAINS);
  645. }
  646.  
  647. /* Find a neighbor table entry.  Neighbors are determined by
  648.  * their callsign and the interface number.  This takes care
  649.  * of the case where the same switch or hosts uses the same
  650.  * callsign on two different channels.  This isn't done by
  651.  * net/rom, but it might be done by stations running *our*
  652.  * software.
  653.  */
  654. static struct nrnbr_tab *
  655. find_nrnbr(addr,ifnum)
  656. register char *addr;
  657. unsigned ifnum;
  658. {
  659.     int16 hashval;
  660.     register struct nrnbr_tab *np;
  661.  
  662.     /* Find appropriate hash chain */
  663.     hashval = nrhash(addr);
  664.  
  665.     /* search hash chain */
  666.     for(np = Nrnbr_tab[hashval]; np != NULLNTAB; np = np->next){
  667.         /* convert first in  list to ax25 address format */
  668.         if(addreq(np->call,addr) && np->iface == ifnum){
  669.             return np;
  670.         }
  671.     }
  672.     return NULLNTAB;
  673. }
  674.  
  675.  
  676. /* Find a route table entry */
  677. struct nrroute_tab *
  678. find_nrroute(addr)
  679. register char *addr;
  680. {
  681.     int16 hashval;
  682.     register struct nrroute_tab *rp;
  683.  
  684.     /* Find appropriate hash chain */
  685.     hashval = nrhash(addr);
  686.  
  687.     /* search hash chain */
  688.     for(rp = Nrroute_tab[hashval]; rp != NULLNRRTAB; rp = rp->next){
  689.         if(addreq(rp->call,addr)){
  690.             return rp;
  691.         }
  692.     }
  693.     return NULLNRRTAB;
  694. }
  695.  
  696. /* Try to find the AX.25 address of a node with the given alias.  Return */
  697. /* a pointer to the AX.25 address if found, otherwise NULLCHAR.  The alias */
  698. /* should be a six character, blank-padded, upper-case string. */
  699.  
  700. char *
  701. find_nralias(alias)
  702. char *alias;
  703. {
  704.     int i;
  705.     register struct nrroute_tab *rp;
  706.  
  707.     /* Since the route entries are hashed by ax.25 address, we'll */
  708.     /* have to search all the chains */
  709.     
  710.     for(i = 0; i < NRNUMCHAINS; i++)
  711.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next)
  712.             if(strncmp(alias, rp->alias, 6) == 0)
  713.                 return rp->call;
  714.  
  715.     /* If we get to here, we're out of luck */
  716.  
  717.     return NULLCHAR;
  718. }
  719.  
  720.  
  721. /* Find a binding in a list by its neighbor structure's address */
  722. static struct nr_bind *
  723. find_binding(list,neighbor)
  724. struct nr_bind *list;
  725. register struct nrnbr_tab *neighbor;
  726. {
  727.     register struct nr_bind *bp;
  728.  
  729.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  730.         if(bp->via == neighbor)
  731.             return bp;
  732.  
  733.     return NULLNRBIND;
  734. }
  735.  
  736. /* Find the worst quality non-permanent binding in a list */
  737. static
  738. struct nr_bind *
  739. find_worst(list)
  740. struct nr_bind *list;
  741. {
  742.     register struct nr_bind *bp;
  743.     struct nr_bind *worst = NULLNRBIND;
  744.     unsigned minqual = 1000;    /* infinity */
  745.  
  746.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  747.         if(!(bp->flags & NRB_PERMANENT) && bp->quality < minqual){
  748.             worst = bp;
  749.             minqual = bp->quality;
  750.         }
  751.  
  752.     return worst;
  753. }
  754.  
  755. /* Find the best binding of any sort in a list.  If obso is 1,
  756.  * include entries below the obsolescence threshhold in the
  757.  * search (used when this is called for routing broadcasts).
  758.  * If it is 0, routes below the threshhold are treated as
  759.  * though they don't exist.
  760.  */
  761. static
  762. struct nr_bind *
  763. find_best(list,obso)
  764. struct nr_bind *list;
  765. unsigned obso;
  766. {
  767.     register struct nr_bind *bp;
  768.     struct nr_bind *best = NULLNRBIND;
  769.     int maxqual = -1;    /* negative infinity */
  770.  
  771.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  772.         if((int)bp->quality > maxqual)
  773.             if(obso || bp->obsocnt >= Obso_minbc){
  774.                 best = bp;
  775.                 maxqual = bp->quality;
  776.             }
  777.  
  778.     return best;
  779. }
  780.  
  781. /* Add a route to the net/rom routing table */
  782. int
  783. nr_routeadd(alias,dest,ifnum,quality,neighbor,permanent,record)
  784. char *alias;        /* net/rom node alias, blank-padded and */
  785.             /* null-terminated */
  786. char *dest;        /* destination node callsign */
  787. unsigned ifnum;    /* net/rom interface number */
  788. unsigned quality;    /* route quality */
  789. char *neighbor;    /* neighbor node + 2 digis (max) in arp format */
  790. unsigned permanent;    /* 1 if route is permanent (hand-entered) */
  791. unsigned record;    /* 1 if route is a "record route" */
  792. {
  793.     struct nrroute_tab *rp;
  794.     struct nr_bind *bp;
  795.     struct nrnbr_tab *np;
  796.     int16 rhash, nhash;
  797.  
  798.     /* See if a routing table entry exists for this destination */
  799.     if((rp = find_nrroute(dest)) == NULLNRRTAB){
  800.         rp = (struct nrroute_tab *)callocw(1,sizeof(struct nrroute_tab));
  801.         /* create a new route table entry */
  802.         strncpy(rp->alias,alias,6);
  803.         memcpy(rp->call,dest,AXALEN);
  804.         rhash = nrhash(dest);
  805.         rp->next = Nrroute_tab[rhash];
  806.         if(rp->next != NULLNRRTAB)
  807.             rp->next->prev = rp;
  808.         Nrroute_tab[rhash] = rp;    /* link at head of hash chain */
  809.     } else if(permanent || !strncmp(rp->alias,"##temp",6)) {
  810.         strncpy(rp->alias,alias,6);    /* update the alias */
  811.     }
  812.  
  813.     /* See if an entry exists for this neighbor */
  814.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB){
  815.         np = (struct nrnbr_tab *)callocw(1,sizeof(struct nrnbr_tab));
  816.         /* create a new neighbor entry */
  817.         memcpy(np->call,neighbor,AXALEN);
  818.         np->iface = ifnum;
  819.         nhash = nrhash(neighbor);
  820.         np->next = Nrnbr_tab[nhash];
  821.         if(np->next != NULLNTAB)
  822.             np->next->prev = np;
  823.         Nrnbr_tab[nhash] = np;
  824.     } else if(permanent){        /* force this path to the neighbor */
  825.         memcpy(np->call,neighbor,AXALEN);
  826.     }
  827.         
  828.     /* See if there is a binding between the dest and neighbor */
  829.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND){
  830.         bp = (struct nr_bind *)callocw(1,sizeof(struct nr_bind));
  831.         /* create a new binding and link it in */
  832.         bp->via = np;    /* goes via this neighbor */
  833.         bp->next = rp->routes;    /* link into binding chain */
  834.         if(bp->next != NULLNRBIND)
  835.             bp->next->prev = bp;
  836.         rp->routes = bp;
  837.         rp->num_routes++;    /* bump route count */
  838.         np->refcnt++;        /* bump neighbor ref count */
  839.         bp->quality = quality;
  840.         bp->obsocnt = Obso_init;    /* use initial value */
  841.         if(permanent)
  842.             bp->flags |= NRB_PERMANENT;
  843.         else if(record)    /* notice permanent overrides record! */
  844.             bp->flags |= NRB_RECORDED;
  845.     } else {
  846.         if(permanent){    /* permanent request trumps all */
  847.             bp->quality = quality;
  848.             bp->obsocnt = Obso_init;
  849.             bp->flags |= NRB_PERMANENT;
  850.             bp->flags &= ~NRB_RECORDED;    /* perm is not recorded */
  851.         } else if(!(bp->flags & NRB_PERMANENT)){    /* not permanent */
  852.             if(record){    /* came from nr_route */
  853.                 if(bp->flags & NRB_RECORDED){ /* no mod non-rec bindings */
  854.                     bp->quality = quality;
  855.                     bp->obsocnt = Obso_init; /* freshen recorded routes */
  856.                 }
  857.             } else {        /* came from a routing broadcast */
  858.                 bp->quality = quality;
  859.                 bp->obsocnt = Obso_init;
  860.                 bp->flags &= ~NRB_RECORDED; /* no longer a recorded route */
  861.             }
  862.         }
  863.     }
  864.  
  865.     /* Now, check to see if we have too many bindings, and drop */
  866.     /* the worst if we do */
  867.     if(rp->num_routes > Nr_maxroutes){
  868.         /* since find_worst never returns permanent entries, the */
  869.         /* limitation on number of routes is circumvented for    */
  870.         /* permanent routes */
  871.         if((bp = find_worst(rp->routes)) != NULLNRBIND){
  872.             nr_routedrop(dest,bp->via->call,bp->via->iface);
  873.         }
  874.     }
  875.  
  876.     return 0;
  877. }
  878.  
  879.  
  880. /* Drop a route to dest via neighbor */
  881. int
  882. nr_routedrop(dest,neighbor,ifnum)
  883. char *dest, *neighbor;
  884. unsigned ifnum;
  885. {
  886.     register struct nrroute_tab *rp;
  887.     register struct nrnbr_tab *np;
  888.     register struct nr_bind *bp;
  889.  
  890.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  891.         return -1;
  892.  
  893.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB)
  894.         return -1;
  895.  
  896.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND)
  897.         return -1;
  898.  
  899.     /* drop the binding first */
  900.     if(bp->next != NULLNRBIND)
  901.         bp->next->prev = bp->prev;
  902.     if(bp->prev != NULLNRBIND)
  903.         bp->prev->next = bp->next;
  904.     else
  905.         rp->routes = bp->next;
  906.  
  907.     free((char *)bp);
  908.     rp->num_routes--;        /* decrement the number of bindings */
  909.     np->refcnt--;            /* and the number of neighbor references */
  910.     
  911.     /* now see if we should drop the route table entry */
  912.     if(rp->num_routes == 0){
  913.         if(rp->next != NULLNRRTAB)
  914.             rp->next->prev = rp->prev;
  915.         if(rp->prev != NULLNRRTAB)
  916.             rp->prev->next = rp->next;
  917.         else
  918.             Nrroute_tab[nrhash(dest)] = rp->next;
  919.  
  920.         free((char *)rp);
  921.     }
  922.  
  923.     /* and check to see if this neighbor can be dropped */
  924.     if(np->refcnt == 0){
  925.         if(np->next != NULLNTAB)
  926.             np->next->prev = np->prev;
  927.         if(np->prev != NULLNTAB)
  928.             np->prev->next = np->next;
  929.         else
  930.             Nrnbr_tab[nrhash(neighbor)] = np->next;
  931.  
  932.         free((char *)np);
  933.     }
  934.     
  935.     return 0;
  936. }
  937.  
  938. #ifdef    notused
  939. /* Find the best neighbor for destination dest, in arp format */
  940. static char *
  941. nr_getroute(dest)
  942. char *dest;
  943. {
  944.     register struct nrroute_tab *rp;
  945.     register struct nr_bind *bp;
  946.  
  947.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  948.         return NULLCHAR;
  949.  
  950.     if((bp = find_best(rp->routes,1)) == NULLNRBIND)    /* shouldn't happen! */
  951.         return NULLCHAR;
  952.  
  953.     return bp->via->call;
  954. }
  955. #endif    /* notused */
  956.  
  957. /* Find an entry in the filter table */
  958. static struct nrnf_tab *
  959. find_nrnf(addr,ifnum)
  960. register char *addr;
  961. unsigned ifnum;
  962. {
  963.     int16 hashval;
  964.     register struct nrnf_tab *fp;
  965.  
  966.     /* Find appropriate hash chain */
  967.     hashval = nrhash(addr);
  968.  
  969.     /* search hash chain */
  970.     for(fp = Nrnf_tab[hashval]; fp != NULLNRNFTAB; fp = fp->next){
  971.         if(addreq(fp->neighbor,addr) && fp->iface == ifnum){
  972.             return fp;
  973.         }
  974.     }
  975.  
  976.     return NULLNRNFTAB;
  977. }
  978.  
  979. /* Add an entry to the filter table.  Return 0 on success,
  980.  * -1 on failure
  981.  */
  982. int
  983. nr_nfadd(addr,ifnum,qual)
  984. char *addr;
  985. unsigned ifnum;
  986. unsigned qual;
  987. {
  988.     struct nrnf_tab *fp;
  989.     int16 hashval;
  990.     
  991.     if(find_nrnf(addr,ifnum) != NULLNRNFTAB)
  992.         return 0;    /* already there; it's a no-op */
  993.  
  994.     fp = (struct nrnf_tab *)callocw(1,sizeof(struct nrnf_tab));
  995.  
  996.     hashval = nrhash(addr);
  997.     memcpy(fp->neighbor,addr,AXALEN);
  998.     fp->iface = ifnum;
  999.     fp->next = Nrnf_tab[hashval];
  1000.     fp->quality = qual;
  1001.     if(fp->next != NULLNRNFTAB)
  1002.         fp->next->prev = fp;
  1003.     Nrnf_tab[hashval] = fp;
  1004.  
  1005.     return 0;
  1006. }
  1007.  
  1008. /* Drop a neighbor from the filter table.  Returns 0 on success, -1
  1009.  * on failure.
  1010.  */
  1011. int
  1012. nr_nfdrop(addr,ifnum)
  1013. char *addr;
  1014. unsigned ifnum;
  1015. {
  1016.     struct nrnf_tab *fp;
  1017.  
  1018.     if((fp = find_nrnf(addr,ifnum)) == NULLNRNFTAB)
  1019.         return -1;    /* not in the table */
  1020.  
  1021.     if(fp->next != NULLNRNFTAB)
  1022.         fp->next->prev = fp->prev;
  1023.     if(fp->prev != NULLNRNFTAB)
  1024.         fp->prev->next = fp->next;
  1025.     else
  1026.         Nrnf_tab[nrhash(addr)] = fp->next;
  1027.  
  1028.     free((char *)fp);
  1029.  
  1030.     return 0;
  1031. }
  1032.  
  1033. /*
  1034.  * Validate the alias field is good quality ascii to prevent network corruption
  1035.  */
  1036.  
  1037. static int
  1038. nr_aliasck(alias)
  1039. char *alias;            
  1040.  
  1041. {
  1042.     int x = ALEN;
  1043.     int c;
  1044.     while (x--) {
  1045.         c = *alias++;
  1046.         if (!isprint( (int) c) )        
  1047.             return 1;
  1048.     }
  1049.     return 0;
  1050. }
  1051.  
  1052. /* called from lapb whenever a link failure implies that a particular ax25
  1053.  * path may not be able to carry netrom traffic too well. Experimental!!!!
  1054.  */
  1055. void nr_derate(axp)
  1056. struct ax25_cb *axp;
  1057. {
  1058.     register struct nrnbr_tab *np ;
  1059.     register struct nrroute_tab *rp;
  1060.     register struct nr_bind *bp;
  1061.     struct mbuf *buf;
  1062.     int i, ifnum;
  1063.     int nr_traffic = 0;    /* assume no netrom traffic on connection */
  1064.  
  1065.     if(!Nr_derate)
  1066.         return;        /* derating function is disabled */
  1067.  
  1068.     /* First, see if this is even a net/rom interface: */
  1069.     if (axp == NULLAX25)
  1070.         return;            /* abandon ship! */
  1071.  
  1072.     /* If it is valid for netrom traffic, lets see if there is */
  1073.     /* really netrom traffic on the connection to be derated.  */
  1074.  
  1075.     for (buf = axp->txq; buf != NULLBUF; buf = buf->anext)
  1076.         if ((buf->data[0] & 0xff) == PID_NETROM)
  1077.             nr_traffic = 1;        /* aha - netrom traffic! */
  1078.  
  1079.     if (!nr_traffic)
  1080.         return;        /* no sign of being used by netrom just now */
  1081.  
  1082.     /* find the interface number */
  1083.     for (ifnum = 0 ; ifnum < Nr_numiface ; ifnum++)
  1084.         if (axp->iface == Nrifaces[ifnum].iface)
  1085.             break ;
  1086.  
  1087.     if (ifnum == Nr_numiface)    /* may well happen! */
  1088.         return ;
  1089.  
  1090.     /* we now have the appropriate interface entry */
  1091.  
  1092.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  1093.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  1094.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  1095.                 np = bp->via;
  1096.                 if(bp->quality >= 1 && np->iface == ifnum &&
  1097.                 !(bp->flags & NRB_PERMANENT) &&
  1098.                 !memcmp(np->call,axp->remote,ALEN) &&
  1099.                 (np->call[6] & SSID) == (axp->remote[6] & SSID)) {
  1100.                     bp->quality = ((bp->quality * 2) / 3);
  1101.                 }
  1102.             }
  1103.         }
  1104.     }
  1105. }
  1106.